<template>
   <div class="time">

     <template v-if="custom == false">
        <slot>{{formattedTime}}</slot>
     </template>

     <template v-if="custom == true">
        <slot :times="timeData"></slot>
     </template>
   </div>
</template>

<script>
let prev = Date.now();
export default {
  name: 'countDown',
  data() {
    return {
      remain: 0,
      rafId: null,
    };
  },
  props: {
    //是否显示自定义倒计时
    custom: {
      type: Boolean,
      default: false
    },
    // 倒计时时长，单位毫秒
    time: {
      type: Number,
      default: 0
    },
    // 时间格式，DD-日，HH-时，mm-分，ss-秒，SSS-毫秒
    format: {
      type: String,
      default: "HH:mm:ss"
    },
    // 是否自动开始倒计时  默認是 自動
    autoStart: {
      type: Boolean,
      default: true
    },
    // 是否开启毫秒级渲染  默認是 不開啓
    millisecond: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    time: {
      immediate: true,
      handler() {
        this.reset();
      }
    }
  },
  methods: {

    //开始
    start() {
      if (this.counting) {
        return;
      }

      this.counting = true;
      this.endTime = Date.now() + this.remain;
      this.tick();
    },

    //暂停
    pause() {
      this.counting = false;
      clearTimeout(this.rafId)
    },

    //重置
    reset() {
      this.remain = this.time - Date.now();
      if (this.autoStart) {
        this.start();
      }
    },

    tick() {
      if (this.millisecond) {
        this.microTick();
      } else {
        this.macroTick();
      }
    },

    microTick() {
        this.rafId = setTimeout(() =>{
            this.setRemain(this.getRemain());
            if (this.remain !== 0) {
              this.microTick();
            }

        },1000)
    },

    macroTick() {
      this.rafId = setTimeout(() =>{
          const remain = this.getRemain();

          if (!this.isSameSecond(remain, this.remain) || remain === 0) {
            this.setRemain(remain);
          }

          if (this.remain !== 0) {
            this.macroTick();
          }

      },1000)

    },
    

    setRemain(remain) {
      this.remain = remain;
      if (remain === 0) {
        this.pause();
        this.$emit('finish');
      }
    },

    getRemain() {
      return Math.max(this.endTime - Date.now(), 0);
    },

    isSameSecond(time1,time2) {
      return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
    },

    

    parseFormat(format,timeData) {
        const { days } = timeData;
        let { hours, minutes, seconds, milliseconds } = timeData;

        if (format.indexOf('DD') === -1) {
          hours += days * 24;
        } else {
          format = format.replace('DD', this.padZero(days));

        }

        if (format.indexOf('HH') === -1) {
          minutes += hours * 60;
        } else {
          format = format.replace('HH', this.padZero(hours));
        }

        if (format.indexOf('mm') === -1) {
          seconds += minutes * 60;
        } else {
          format = format.replace('mm', this.padZero(minutes));
        }

        if (format.indexOf('ss') === -1) {
          milliseconds += seconds * 1000;
        } else {
          format = format.replace('ss', this.padZero(seconds));
        }

        return format.replace('SSS', this.padZero(milliseconds));

    },

    parseTimeData(time) {
      const SECOND = 1000;
      const MINUTE = 60 * SECOND;
      const HOUR = 60 * MINUTE;
      const DAY = 24 * HOUR;

      const days = this.padZero(Math.floor(time / DAY));
      const hours = this.padZero(Math.floor((time % DAY) / HOUR));
      const minutes = this.padZero(Math.floor((time % HOUR) / MINUTE));
      const seconds = this.padZero(Math.floor((time % MINUTE) / SECOND));
      const milliseconds = this.padZero(Math.floor(time % SECOND));

      
      

       return {
        days,
        hours,
        minutes,
        seconds,
        milliseconds
      }; 

    },

    padZero(num, targetLength) {
        if (targetLength === void 0) { targetLength = 2; }
        var str = num + '';
        while (str.length < targetLength) {
            str = '0' + str;
        }
        return str;
    },
    
  },
  computed: {
      timeData() {
        return this.parseTimeData(this.remain);
      },
      formattedTime() {
        return this.parseFormat(this.format, this.timeData);
      }
  },
  destroyed() {
    if (this.rafId) {
      this.pause();
    }
  }

  // render: function (createElement) {

  //   // `<div><slot :text="message"></slot></div>`
  //   return createElement('div', [
  //     this.$scopedSlots.default({
  //       timeData: this.timeData
  //     })
  //   ])
  // }

  
};
</script>

<style>
</style>
